package cn.xd.base.domain.entity;

import cn.xd.base.basic.type.*;
import cn.xd.base.domain.bean.command.AddAdminRoleCommand;
import cn.xd.base.domain.bean.command.UpdateAdminRoleCommand;
import cn.xd.base.domain.bean.command.common.ChangeStatusCommand;
import cn.xd.core.basic.common.CreatorId;
import cn.xd.core.basic.common.UpdateTime;
import cn.xd.core.basic.common.UpdaterId;
import cn.xd.common.enums.common.CommonStatusEnum;
import cn.xd.core.ddd.entity.Aggregate;
import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
public class AdminRole implements Aggregate<AdminRoleId> {
    private AdminRoleId id;
    private AdminRoleName name;
    private AdminRoleDescription description;
    private AdminRoleDataScope dataScope;
    private AdminRoleStatus status;
    private CreatorId creatorId;
    private cn.xd.core.basic.common.CreateTime createTime;
    private UpdaterId updaterId;
    private UpdateTime updateTime;

    private List<AdminRoleMenu> menus;

    private List<AdminOrgRole> orgs;

    /**
     * 新增角色
     *
     * @param command
     * @param userId
     * @return
     */
    public static AdminRole add(AddAdminRoleCommand command, Long userId) {
        AdminRole adminRole = new AdminRole();
        adminRole.setName(AdminRoleName.of(command.getName()));
        adminRole.setDescription(AdminRoleDescription.of(command.getDescription()));
        adminRole.setDataScope(AdminRoleDataScope.of(command.getDataScope()));
        adminRole.setStatus(AdminRoleStatus.of(command.getStatus()));
        adminRole.setCreatorId(CreatorId.of(userId));
        adminRole.setCreateTime(cn.xd.core.basic.common.CreateTime.now());
        adminRole.setUpdaterId(UpdaterId.of(userId));
        adminRole.setUpdateTime(UpdateTime.now());
        adminRole.setMenus(command.getMenuIds().stream().map(item -> AdminRoleMenu.builder().menuId(AdminMenuId.of(item)).createTime(cn.xd.core.basic.common.CreateTime.now()).creatorId(CreatorId.of(userId)).build()).toList());

        adminRole.setOrgs(command.getOrgIds().stream().map(item -> AdminOrgRole.builder().orgId(AdminOrgId.of(item)).createTime(cn.xd.core.basic.common.CreateTime.now()).creatorId(CreatorId.of(userId)).build()).toList());
        return adminRole;
    }

    /**
     * 更新角色
     *
     * @param command
     * @param userId
     */
    public void update(UpdateAdminRoleCommand command, List<AdminOrgRole> adminOrgRoles, List<AdminOrgRole> completeAdminOrgRole, Long userId) {
        this.setDescription(AdminRoleDescription.of(command.getDescription()));
        this.setName(AdminRoleName.of(command.getName()));
        this.setDataScope(AdminRoleDataScope.of(command.getDataScope()));
        this.setStatus(AdminRoleStatus.of(command.getStatus()));
        this.setUpdaterId(UpdaterId.of(userId));
        this.setUpdateTime(UpdateTime.now());
        this.setMenus(command.getMenuIds().stream().map(item -> AdminRoleMenu.builder().menuId(AdminMenuId.of(item)).roleId(AdminRoleId.of(this.getId().getValue()))
                .createTime(cn.xd.core.basic.common.CreateTime.now()).creatorId(CreatorId.of(userId)).build()).toList());
        Map<Long, AdminOrgRole> maps = new HashMap<>();
        List<Long> orgIds = new ArrayList<>();
        for (AdminOrgRole adminOrgRole : adminOrgRoles) {
            orgIds.add(adminOrgRole.getOrgId().getValue());
            maps.put(adminOrgRole.getOrgId().getValue(), adminOrgRole);
        }
        List<AdminOrgRole> orgRoles = new ArrayList<>(command.getOrgIds().stream().map(item -> {
            if (orgIds.contains(item)) {
                return maps.get(item);
            }
            return AdminOrgRole.builder().orgId(AdminOrgId.of(item)).roleId(AdminRoleId.of(this.getId().getValue()))
                    .createTime(cn.xd.core.basic.common.CreateTime.now()).creatorId(CreatorId.of(userId)).build();
        }).toList());
        orgRoles.addAll(completeAdminOrgRole);
        this.setOrgs(orgRoles);
    }


    /**
     * 修改状态
     *
     * @param command
     * @param userId
     */
    public void changeStatus(ChangeStatusCommand command, Long userId) {
        this.setStatus(AdminRoleStatus.of(command.getStatus()));
        this.setUpdaterId(UpdaterId.of(userId));
        this.setUpdateTime(UpdateTime.now());
    }

    /**
     * 删除角色
     */
    public void delete() {
        this.setStatus(AdminRoleStatus.of(CommonStatusEnum.DELETED.getCode()));

    }
}
